package org.surelink.radius.middleware.acct;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.surelink.radius.cache.GroupCache;
import org.surelink.radius.cache.OnlineCache;
import org.surelink.radius.cache.UserCache;
import org.surelink.radius.constant.FeePolicys;
import org.surelink.radius.middleware.AcctMiddleware;
import org.surelink.radius.model.Ticket;
import org.surelink.radius.model.User;
import org.surelink.radius.model.Online;
import org.surelink.radius.utils.DateTimeUtil;
import org.surelink.radius.utils.ValidateUtil;
import org.tinyradius.packet.AccountingRequest;
import org.surelink.radius.constant.Constant;

/**
 * 记账下线包处理
 */
public class AcctStopMiddleware implements AcctMiddleware
{

    private static final Logger logger = Logger.getLogger(AcctStopMiddleware.class);

    private static final Logger acctLog = Logger.getLogger("acct");

    @Autowired
    private UserCache userCache;

    @Autowired
    private GroupCache groupCache;

    @Autowired
    private OnlineCache onlineCache;


    public void onAcct(User user, AccountingRequest request) throws Exception {

        if(request.getAcctStatusType()!=AccountingRequest.ACCT_STATUS_TYPE_STOP)
            return;

        String client = request.getAttributeValue("NAS-IP-Address");

        Ticket ticket = Ticket.fromRequest(request);
        if (ticket.getNasIpAddress() == null)
            ticket.setNasIpAddress(client);

        Online online = onlineCache.del(client, ticket.getAcctSessionId());
        if (online == null)
        {
            // 计算起始时间
            int sessionTime = ticket.getAcctSessionTime();
            String stopTime = DateTimeUtil.getDateTimeString();
            String startTime = DateTimeUtil.getPreviousDateTimeBySecondString(stopTime, sessionTime);
            ticket.setAcctStartTime(startTime);
            ticket.setAcctStopTime(stopTime);
            ticket.setStopSource(AccountingRequest.ACCT_STATUS_TYPE_STOP);
            ticket.setStartSource(AccountingRequest.ACCT_STATUS_TYPE_STOP);
        }
        else
        {
            ticket.setAcctStartTime(online.getAcctStart());
            ticket.setAcctStopTime(DateTimeUtil.getDateTimeString());
            ticket.setStopSource(online.getStartSource());
            ticket.setStartSource(AccountingRequest.ACCT_STATUS_TYPE_STOP);
            if (ValidateUtil.isEmpty(ticket.getFramedIpAddress()))
                ticket.setFramedIpAddress(online.getIpAddress());
        }

        if(user==null)
        {
            acctLog.info(ticket.toTicket());
            return;
        }

        String policy = groupCache.getGroupMeta(user.getGroupName(), Constant.GROUP_FEE_POLICY.value());
        String price = groupCache.getGroupMeta(user.getGroupName(), Constant.GROUP_FEE_PRICE.value());
        int _price = price!=null?Integer.valueOf(price):0;
        if(policy!=null)
        {
            int _policy = Integer.valueOf(policy);
            if(_policy== FeePolicys.PrePay_Month.value())
            {
                ticket.setAcctFee(0);
                ticket.setFeeReceivables(0);
                ticket.setIsDeduct(0);
                acctLog.info(ticket.toTicket());
            }
            else if(_policy==FeePolicys.PrePay_TimeLen.value())
            {
                String userCredit = userCache.getUserMeta(user.getUserName(), Constant.USER_CREDIT.value());
                 userCredit = doPrePayTimeLen(userCredit,_price, ticket);
                userCache.setUserMeta(user.getUserName(), Constant.USER_CREDIT.value(),userCredit);
            }
        }
    }

    /**
     * 预付费计时扣费
     * @param userCredit
     * @param price
     * @param ticket
     * @return
     */
    private String doPrePayTimeLen(String userCredit,int price,Ticket ticket)
    {

        if(userCredit == null)
            return "0";

        int credit = Integer.valueOf(userCredit);
        int usedMimiter = (ticket.getAcctSessionTime() - 1) / 60 + 1;
        int usedFee = (int) (usedMimiter / 60 * price);
        int remainder = (int) (usedMimiter % 60);

        if (remainder > 0)
        {
            usedFee = usedFee + remainder * price / 60;
        }

        int balance = credit - usedFee;

        if (balance < 0)
        {// 余额不足
            userCredit = "0";
        }
        else
        {
            userCredit = String.valueOf(balance);
        }

        ticket.setAcctFee(usedFee);
        ticket.setFeeReceivables(usedFee);
        ticket.setIsDeduct(1);
        acctLog.info(ticket.toTicket());
        return userCredit;
    }

}
